package cn.clx.ymcc.service.impl;

import cn.clx.ymcc.domain.KillActivity;
import cn.clx.ymcc.domain.KillCourse;
import cn.clx.ymcc.mapper.KillActivityMapper;
import cn.clx.ymcc.service.IKillActivityService;
import cn.clx.ymcc.service.IKillCourseService;
import cn.clx.ymcc.util.AssertUtil;
import cn.clx.ymcc.util.RedisConfig;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author clx
 * @since 2022-08-04
 */
@Service
@Slf4j
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM-dd HH:ss");

    @Autowired
    private IKillCourseService killCourseService;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 添加秒杀活动
     * @param killActivity
     */
    @Override
    public void save(KillActivity killActivity) {
        //校验参数 ----- 这里就不校验了
        killActivity.setTimeStr(simpleDateFormat.format(killActivity.getStartTime()));
        insert(killActivity);
    }

    /**
     * 秒杀活动发布
     * @param activityId
     */
    @Override
    public void publish(Long activityId) {

        KillActivity killActivity = selectById(activityId);
        AssertUtil.isNotNull(killActivity,"该秒杀活动不存在");
        boolean OK = killActivity.getPublishStatus().intValue() == 0;
        AssertUtil.isTrue(OK,"该活动已经发布了");
        Date now = new Date();
        killActivity.setPublishTime(now);
        killActivity.setPublishStatus(1);

        //要把该秒杀活动中的所有课程数据存储到redis中============
        //判断该活动时间是否还有效
        boolean after = killActivity.getStartTime().after(now);
        AssertUtil.isTrue(after,"活动时间错误，请核对");
        List<KillCourse> killCourses = selectListByactivityId(activityId);

        for (KillCourse killCourse : killCourses) {

            killCourse.setPublishStatus(1);
            killCourse.setPublishTime(now);
            killCourseService.updateById(killCourse);

            //还要设置信号量，使用redisionClient 客户端来设置信号量
            String key = activityId+":"+killCourse.getId();
            // 使用活动id+课程id作为分布式信号量
            RSemaphore semaphore = redissonClient.getSemaphore(key);
            boolean Signal = semaphore.trySetPermits(killCourse.getKillCount());
            if(Signal){ //信号量设置是否成功
                log.info("添加秒杀课程成功！{}",killCourse.getCourseName());
                //使用hash来存储数据
                redisTemplate.opsForHash().put("activity:"+activityId,killCourse.getId().toString(),killCourse);
            }else {
                //重试机制
                //返回兜底数据
                //记录数据库，发短信，站内信 通知相关人员
                log.info("添加秒杀课程失败！{}",killCourse.getCourseName());
            }

        }
        killActivity.setPublishStatus(1);
        updateById(killActivity);
    }

    public List<KillCourse> selectListByactivityId(Long activityId){
        Wrapper<KillCourse> wrapper= new EntityWrapper<>();
        wrapper.eq("activity_id",activityId);
        return killCourseService.selectList(wrapper);
    }

}
